home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / pc / DirectX SDK / DXSDK / samples / Multimedia / DirectPlay / Maze / MazeServer / server.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-10-31  |  15.5 KB  |  497 lines

  1. //----------------------------------------------------------------------------
  2. // File: server.cpp
  3. //
  4. // Desc: see main.cpp
  5. //
  6. // Copyright (c) 1999-2001 Microsoft Corp. All rights reserved.
  7. //-----------------------------------------------------------------------------
  8. #define STRICT
  9. #include <windows.h>
  10. #include <process.h>
  11. #include <stdio.h>
  12. #include <math.h>
  13. #include <stdio.h>
  14. #include <tchar.h>
  15. #include <conio.h>
  16. #include <dplay8.h>
  17. #include <dpaddr.h>
  18. #include <DXErr8.h>
  19. #include "DXUtil.h"
  20. #include "server.h"
  21. #include "StressMazeGUID.h"
  22.  
  23. #define DPMAZESERVER_PORT       2309
  24.       
  25.  
  26.  
  27.  
  28. //-----------------------------------------------------------------------------
  29. // Name: 
  30. // Desc: 
  31. //-----------------------------------------------------------------------------
  32. CDPlay8Server::CDPlay8Server()
  33. {
  34.     m_pDPlay    = NULL;
  35.     m_pServer   = NULL;
  36. }
  37.  
  38.  
  39.  
  40.  
  41. //-----------------------------------------------------------------------------
  42. // Name: 
  43. // Desc: 
  44. //-----------------------------------------------------------------------------
  45. HRESULT CDPlay8Server::Start(DWORD dwNumSPThreads)
  46. {
  47.     HRESULT hr;
  48.     PDIRECTPLAY8ADDRESS   pDP8AddrLocal = NULL;
  49.     DWORD dwPort;
  50.  
  51.     // Create DirectPlay object
  52.     hr = CoCreateInstance( CLSID_DirectPlay8Server, NULL, 
  53.                            CLSCTX_ALL, IID_IDirectPlay8Server,
  54.                            (LPVOID*) &m_pDPlay );
  55.     if( FAILED(hr) )
  56.     {
  57.         DXTRACE_ERR( TEXT("CoCreateInstance"), hr );
  58.         goto LCleanup;
  59.     }
  60.  
  61.     hr = CoCreateInstance( CLSID_DirectPlay8Address, NULL, 
  62.                            CLSCTX_ALL, IID_IDirectPlay8Address, 
  63.                            (LPVOID*) &pDP8AddrLocal );
  64.     if( FAILED(hr) )
  65.     {
  66.         DXTRACE_ERR( TEXT("CoCreateInstance"), hr );
  67.         goto LCleanup;
  68.     }
  69.  
  70.     hr = pDP8AddrLocal->SetSP( &CLSID_DP8SP_TCPIP );
  71.     if( FAILED(hr) )
  72.     {
  73.         DXTRACE_ERR( TEXT("BuildLocalAddress"), hr );
  74.         goto LCleanup;
  75.     }
  76.  
  77.     dwPort = DPMAZESERVER_PORT;
  78.     hr = pDP8AddrLocal->AddComponent( DPNA_KEY_PORT, 
  79.                                       &dwPort, sizeof(dwPort),
  80.                                       DPNA_DATATYPE_DWORD );
  81.     if( FAILED(hr) )
  82.     {
  83.         DXTRACE_ERR( TEXT("BuildLocalAddress"), hr );
  84.         goto LCleanup;
  85.     }
  86.  
  87.     
  88.     hr = m_pDPlay->Initialize( this, StaticReceiveHandler, 0 );
  89.     if( FAILED(hr) )
  90.     {
  91.         DXTRACE_ERR( TEXT("Initialize"), hr );
  92.         goto LCleanup;
  93.     }
  94.  
  95.     // If greater than 0, and less than 128, attempt to set number of threads.
  96.     if((dwNumSPThreads >= MIN_SP_THREADS) && (dwNumSPThreads <= MAX_SP_THREADS))
  97.     {
  98.         // Set the number of SP Threads
  99.         SetNumSPThreads(dwNumSPThreads);
  100.  
  101.     }
  102.  
  103.     
  104.     DPN_APPLICATION_DESC dpnAppDesc;
  105.     ZeroMemory( &dpnAppDesc, sizeof(DPN_APPLICATION_DESC) );
  106.     dpnAppDesc.dwSize = sizeof( DPN_APPLICATION_DESC );
  107.     dpnAppDesc.dwFlags = DPNSESSION_CLIENT_SERVER;
  108.     dpnAppDesc.guidApplication = StressMazeAppGUID;
  109.     dpnAppDesc.pwszSessionName = L"StressMazeServer Session";
  110.  
  111.     // Set host player context to non-NULL so we can determine which player indication is 
  112.     // the host's.
  113.     hr = m_pDPlay->Host( &dpnAppDesc, &pDP8AddrLocal, 1, NULL, NULL, (void *) 1, 0  );
  114.     if( FAILED(hr) )
  115.     {
  116.         DXTRACE_ERR( TEXT("Host"), hr );
  117.         goto LCleanup;
  118.     }
  119.  
  120. LCleanup:
  121.     SAFE_RELEASE( pDP8AddrLocal );
  122.     SAFE_RELEASE( pDP8AddrLocal );
  123.  
  124.     return hr;
  125. }
  126.  
  127.  
  128.  
  129. //-----------------------------------------------------------------------------
  130. // Name: 
  131. // Desc: 
  132. //-----------------------------------------------------------------------------
  133. DWORD CDPlay8Server::GetNumSPThreads()
  134. {
  135.  
  136.     HRESULT             hr = DPN_OK;
  137.  
  138.     DPN_SP_CAPS         dnSPCaps;
  139.     DWORD               dwFlags = NULL;
  140.     DWORD               dwNumSPThreads = NULL;
  141.  
  142.     DXTRACE_MSG( TEXT("Attempting to Get SP Thread Count.") );
  143.  
  144.     dnSPCaps.dwSize = sizeof(DPN_SP_CAPS);
  145.     
  146.     hr = m_pDPlay->GetSPCaps(&CLSID_DP8SP_TCPIP, &dnSPCaps, dwFlags);
  147.     if(hr != DPN_OK)
  148.     {
  149.         DXTRACE_ERR( TEXT("GetSPCaps error"), hr );
  150.         dwNumSPThreads = 0xffffffff;
  151.     }
  152.     else
  153.     {
  154.         dwNumSPThreads = dnSPCaps.dwNumThreads;
  155.     }
  156.  
  157.     return dwNumSPThreads;
  158.  
  159. }
  160.  
  161.  
  162. //-----------------------------------------------------------------------------
  163. // Name: 
  164. // Desc: 
  165. //-----------------------------------------------------------------------------
  166. void CDPlay8Server::SetNumSPThreads(DWORD dwNumSPThreads)
  167. {
  168.     HRESULT             hr = DPN_OK;
  169.     
  170.     DPN_SP_CAPS         dnSPCaps;
  171.     DWORD               dwFlags = NULL;
  172.  
  173.     dnSPCaps.dwSize = sizeof(DPN_SP_CAPS);
  174.     hr = m_pDPlay->GetSPCaps(&CLSID_DP8SP_TCPIP, &dnSPCaps, dwFlags);
  175.     if(hr == DPN_OK)
  176.     {
  177.         if((dwNumSPThreads >= MIN_SP_THREADS) && (dwNumSPThreads <= MAX_SP_THREADS))
  178.         {
  179.             dnSPCaps.dwNumThreads = dwNumSPThreads;
  180.             
  181.             // Attempt to set the number of SP Threads.
  182.             hr = m_pDPlay->SetSPCaps(&CLSID_DP8SP_TCPIP, &dnSPCaps, dwFlags);
  183.             if(hr != DPN_OK)
  184.             {
  185.                 DXTRACE_ERR( TEXT("SetSPCaps error."), hr );
  186.             }
  187.         }
  188.     }
  189.     else
  190.     {
  191.         DXTRACE_ERR( TEXT("GetSPCaps error."), hr );
  192.     }
  193.  
  194. }
  195.  
  196. //-----------------------------------------------------------------------------
  197. // Name: 
  198. // Desc: 
  199. //-----------------------------------------------------------------------------
  200. DWORD CDPlay8Server::GetSPBuffer()
  201. {
  202.  
  203.     HRESULT             hr = DPN_OK;
  204.  
  205.     DPN_SP_CAPS         dnSPCaps;
  206.     DWORD               dwFlags = NULL;
  207.     DWORD               dwSPBufferSize = NULL;
  208.  
  209.     DXTRACE_MSG( TEXT("Attempting to Get SP Buffer Size.") );
  210.  
  211.     dnSPCaps.dwSize = sizeof(DPN_SP_CAPS);
  212.     
  213.     hr = m_pDPlay->GetSPCaps(&CLSID_DP8SP_TCPIP, &dnSPCaps, dwFlags);
  214.     if(hr != DPN_OK)
  215.     {
  216.         DXTRACE_ERR( TEXT("GetSPCaps error"), hr );
  217.         dwSPBufferSize = 0xffffffff;
  218.     }
  219.     else
  220.     {
  221.         dwSPBufferSize = dnSPCaps.dwSystemBufferSize;
  222.     }
  223.  
  224.     return dwSPBufferSize;
  225.  
  226. }
  227.  
  228.  
  229. //-----------------------------------------------------------------------------
  230. // Name: 
  231. // Desc: 
  232. //-----------------------------------------------------------------------------
  233. void CDPlay8Server::SetSPBuffer(DWORD dwSPBufferSize)
  234. {
  235.     HRESULT             hr = DPN_OK;
  236.     
  237.     DPN_SP_CAPS         dnSPCaps;
  238.     DWORD               dwFlags = NULL;
  239.  
  240.     dnSPCaps.dwSize = sizeof(DPN_SP_CAPS);
  241.     hr = m_pDPlay->GetSPCaps(&CLSID_DP8SP_TCPIP, &dnSPCaps, dwFlags);
  242.     if(hr == DPN_OK)
  243.     {
  244.         if(dwSPBufferSize <= MAX_SP_BUFFER)
  245.             dnSPCaps.dwSystemBufferSize = dwSPBufferSize;
  246.  
  247.         // Attempt to set the number of SP Threads.
  248.         hr = m_pDPlay->SetSPCaps(&CLSID_DP8SP_TCPIP, &dnSPCaps, dwFlags);
  249.         if(hr != DPN_OK)
  250.         {
  251.             DXTRACE_ERR( TEXT("SetSPCaps error."), hr );
  252.         }
  253.     }
  254.     else   
  255.     {
  256.         DXTRACE_ERR( TEXT("GetSPCaps error."), hr );
  257.     }
  258.  
  259. }
  260.  
  261. //-----------------------------------------------------------------------------
  262. // Name: 
  263. // Desc: 
  264. //-----------------------------------------------------------------------------
  265. void CDPlay8Server::Shutdown()
  266. {
  267.     if( m_pDPlay != NULL )
  268.         m_pDPlay->Close(0);
  269.  
  270.     SAFE_RELEASE( m_pDPlay );
  271. }
  272.  
  273.  
  274.  
  275.  
  276. //-----------------------------------------------------------------------------
  277. // Name: 
  278. // Desc: 
  279. //-----------------------------------------------------------------------------
  280. HRESULT CDPlay8Server::RejectClient( DWORD dwID, HRESULT hrReason )
  281. {
  282.     HRESULT hrRet = S_OK;
  283.  
  284.     if( m_pDPlay )
  285.     {
  286.         hrRet = m_pDPlay->DestroyClient( dwID, &hrReason, sizeof(hrReason), 0 );
  287.     }
  288.  
  289.     return hrRet;
  290. }
  291.  
  292.  
  293.  
  294.  
  295. //-----------------------------------------------------------------------------
  296. // Name: 
  297. // Desc: 
  298. //-----------------------------------------------------------------------------
  299. HRESULT CDPlay8Server::StaticReceiveHandler( void *pvContext, DWORD dwMessageType, 
  300.                                              void *pvMessage )
  301. {
  302.     CDPlay8Server* pThisObject = (CDPlay8Server*) pvContext;
  303.  
  304.     return pThisObject->ReceiveHandler( pvContext, dwMessageType, pvMessage );
  305. }
  306.  
  307.  
  308.  
  309. //-----------------------------------------------------------------------------
  310. // Name: 
  311. // Desc: 
  312. //-----------------------------------------------------------------------------
  313. HRESULT CDPlay8Server::ReceiveHandler( void *pvContext, DWORD dwMessageType, 
  314.                                        void *pvMessage )
  315. {
  316.     switch( dwMessageType )
  317.     {
  318.         case DPN_MSGID_CREATE_PLAYER:
  319.         {
  320.             PDPNMSG_CREATE_PLAYER pCreatePlayer = (PDPNMSG_CREATE_PLAYER) pvMessage;
  321.  
  322.             if( pCreatePlayer->pvPlayerContext == NULL )
  323.                 m_pServer->OnAddConnection( pCreatePlayer->dpnidPlayer );
  324.             break;
  325.         }
  326.         
  327.         case DPN_MSGID_DESTROY_PLAYER:
  328.         {
  329.             PDPNMSG_DESTROY_PLAYER pDestroyPlayer = (PDPNMSG_DESTROY_PLAYER) pvMessage;
  330.  
  331.             if( pDestroyPlayer->pvPlayerContext == NULL )
  332.                 m_pServer->OnRemoveConnection( pDestroyPlayer->dpnidPlayer );
  333.             break;
  334.         }
  335.  
  336.         case DPN_MSGID_RECEIVE:
  337.         {
  338.             PDPNMSG_RECEIVE pRecvData = (PDPNMSG_RECEIVE) pvMessage;
  339.  
  340.             m_pServer->OnPacket( pRecvData->dpnidSender, pRecvData->pReceiveData, pRecvData->dwReceiveDataSize );
  341.             break;
  342.         }
  343.  
  344.         case DPN_MSGID_TERMINATE_SESSION:
  345.         {
  346.             m_pServer->OnSessionLost( DISCONNNECT_REASON_UNKNOWN );
  347.             break;
  348.         }
  349.     }
  350.     
  351.     return DPN_OK;
  352. }
  353.  
  354.  
  355.  
  356.  
  357. //-----------------------------------------------------------------------------
  358. // Name: 
  359. // Desc: 
  360. //-----------------------------------------------------------------------------
  361. HRESULT CDPlay8Server::SendPacket( DWORD dwTo, void* pData, 
  362.                                    DWORD dwSize, BOOL bGuaranteed,
  363.                                    DWORD dwTimeout )
  364. {
  365.     DPNHANDLE       hAsync;
  366.     DPNHANDLE*      phAsync;
  367.     DWORD           dwFlags = 0;
  368.     DPN_BUFFER_DESC dpnBufferDesc;
  369.  
  370.     if( bGuaranteed )
  371.     {
  372.         // If we are guaranteed then we must specify
  373.         // DPNSEND_NOCOMPLETE and pass in non-null for the 
  374.         // pvAsyncContext
  375.         dwFlags = DPNSEND_GUARANTEED;
  376.     }
  377.     else
  378.     {
  379.         // If we aren't guaranteed then we can
  380.         // specify DPNSEND_NOCOMPLETE.  And when 
  381.         // DPNSEND_NOCOMPLETE is on pvAsyncContext
  382.         // must be NULL.
  383.         dwFlags = DPNSEND_NOCOMPLETE;
  384.     }
  385.     // Must define an async handle for the SendTo call. 
  386.     phAsync = &hAsync;
  387.  
  388.     dpnBufferDesc.dwBufferSize = dwSize;
  389.     dpnBufferDesc.pBufferData = (PBYTE) pData;
  390.  
  391.     // DirectPlay will tell via the message handler 
  392.     // if there are any severe errors, so ignore any errors 
  393.     m_pDPlay->SendTo( dwTo, &dpnBufferDesc, 1, dwTimeout, NULL, phAsync, dwFlags );
  394.  
  395.     return S_OK;
  396. }
  397.  
  398.  
  399.  
  400.  
  401. //-----------------------------------------------------------------------------
  402. // Name: 
  403. // Desc: 
  404. //-----------------------------------------------------------------------------
  405. HRESULT CDPlay8Server::GetConnectionInfo( DWORD dwID, TCHAR* strConnectionInfo )
  406. {
  407.     HRESULT hr;
  408.  
  409.     // Call GetConnectionInfo and display results
  410.     DPN_CONNECTION_INFO dpnConnectionInfo;
  411.     ZeroMemory( &dpnConnectionInfo, sizeof(DPN_CONNECTION_INFO) );
  412.     dpnConnectionInfo.dwSize = sizeof(DPN_CONNECTION_INFO);
  413.     hr = m_pDPlay->GetConnectionInfo( dwID, &dpnConnectionInfo, 0 );
  414.  
  415.     if( SUCCEEDED(hr) )
  416.     {
  417.         DWORD dwHighPriMessages, dwHighPriBytes;
  418.         DWORD dwNormalPriMessages, dwNormalPriBytes;
  419.         DWORD dwLowPriMessages, dwLowPriBytes;
  420.  
  421.         hr = m_pDPlay->GetSendQueueInfo( dwID,
  422.                                       &dwHighPriMessages, &dwHighPriBytes, 
  423.                                       DPNGETSENDQUEUEINFO_PRIORITY_HIGH );
  424.  
  425.         hr = m_pDPlay->GetSendQueueInfo( dwID,
  426.                                       &dwNormalPriMessages, &dwNormalPriBytes, 
  427.                                       DPNGETSENDQUEUEINFO_PRIORITY_NORMAL );
  428.  
  429.         hr = m_pDPlay->GetSendQueueInfo( dwID,
  430.                                       &dwLowPriMessages, &dwLowPriBytes, 
  431.                                       DPNGETSENDQUEUEINFO_PRIORITY_LOW );
  432.  
  433.         _stprintf( strConnectionInfo, 
  434.                    TEXT("     Round Trip Latency MS=%dms\n")                      \
  435.                    TEXT("     Throughput BPS: Current=%d Peak=%d\n")              \
  436.                                                                             \
  437.                    TEXT("     Messages Received=%d\n")                            \
  438.                                                                             \
  439.                    TEXT("     Sent: GB=%d GP=%d NGB=%d NGP=%d\n")                 \
  440.                    TEXT("     Received: GB=%d GP=%d NGB=%d NGP=%d\n")             \
  441.                                                                             \
  442.                    TEXT("     Messages Transmitted: HP=%d NP=%d LP=%d\n")         \
  443.                    TEXT("     Messages Timed Out: HP=%d NP=%d LP=%d\n")           \
  444.                                                                             \
  445.                    TEXT("     Retried: GB=%d GP=%d\n")                            \
  446.                    TEXT("     Dropped: NGB=%d NGP=%d\n")                          \
  447.                                                                             \
  448.                    TEXT("     Send Queue Messages: HP=%d NP=%d LP=%d\n")          \
  449.                    TEXT("     Send Queue Bytes: HP=%d NP=%d LP=%d\n"),            \
  450.                                                                             \
  451.                                                                             \
  452.                    dpnConnectionInfo.dwRoundTripLatencyMS, 
  453.                    dpnConnectionInfo.dwThroughputBPS, 
  454.                    dpnConnectionInfo.dwPeakThroughputBPS,
  455.  
  456.                    dpnConnectionInfo.dwMessagesReceived,
  457.  
  458.                    dpnConnectionInfo.dwBytesSentGuaranteed,
  459.                    dpnConnectionInfo.dwPacketsSentGuaranteed,
  460.                    dpnConnectionInfo.dwBytesSentNonGuaranteed,
  461.                    dpnConnectionInfo.dwPacketsSentNonGuaranteed,
  462.  
  463.                    dpnConnectionInfo.dwBytesReceivedGuaranteed,
  464.                    dpnConnectionInfo.dwPacketsReceivedGuaranteed,
  465.                    dpnConnectionInfo.dwBytesReceivedNonGuaranteed,
  466.                    dpnConnectionInfo.dwPacketsReceivedNonGuaranteed,
  467.  
  468.                    dpnConnectionInfo.dwMessagesTransmittedHighPriority,
  469.                    dpnConnectionInfo.dwMessagesTransmittedNormalPriority,
  470.                    dpnConnectionInfo.dwMessagesTransmittedLowPriority,
  471.  
  472.                    dpnConnectionInfo.dwMessagesTimedOutHighPriority,
  473.                    dpnConnectionInfo.dwMessagesTimedOutNormalPriority,
  474.                    dpnConnectionInfo.dwMessagesTimedOutLowPriority,
  475.  
  476.                    dpnConnectionInfo.dwBytesRetried,
  477.                    dpnConnectionInfo.dwPacketsRetried,
  478.  
  479.                    dpnConnectionInfo.dwBytesDropped,
  480.                    dpnConnectionInfo.dwPacketsDropped,
  481.  
  482.                    dwHighPriMessages, dwNormalPriMessages, dwLowPriMessages, 
  483.                    dwHighPriBytes, dwNormalPriBytes, dwLowPriBytes
  484.  
  485.                    );
  486.  
  487.     }
  488.     else
  489.     {
  490.         _tcscpy( strConnectionInfo, TEXT("DPNID not found.\n") );
  491.     }
  492.  
  493.     return S_OK;
  494. }
  495.  
  496.  
  497.